package com.uinnova.product.eam.db.support.dao.mybatis;

import com.binary.jdbc.Page;
import com.github.pagehelper.PageHelper;
import com.uinnova.product.eam.db.support.dao.ComMyBatisSQLDao;
import com.uinnova.product.eam.db.support.util.ResultSetConvertUtil;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.scripting.defaults.RawSqlSource;
import org.apache.ibatis.scripting.xmltags.DynamicSqlSource;
import org.apache.ibatis.scripting.xmltags.TextSqlNode;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ComMyBatisSQLDaoImpl extends SqlSessionDaoSupport implements ComMyBatisSQLDao {

	protected Logger log = LoggerFactory.getLogger(ComMyBatisBinaryDaoImpl.class);
	
	private Map<String,String> mapStatementSQL = new HashMap<String,String>(); 
	
	public static final Object obj = new Object();
	
	@Autowired
	private DataSourceTransactionManager transactionManager;
	
	@Override
	public <T> Page<T> queryByPage(String statementid, String sql, Map<String,Object> mapParams,long pageNum,long pageSize,Class<T> beanClass){
		
		
		List<T> listData =  new ArrayList<T>();
		Page<T> page = new Page<T>();
		
		int iPageNum = (int)pageNum;
		int iPageSize = (int)pageSize;
		com.github.pagehelper.Page<Object> pageHelper = PageHelper.startPage(iPageNum,iPageSize,true);
		
		SqlSessionTemplate st = (SqlSessionTemplate) getSqlSession();
				
        if (!st.getConfiguration().hasStatement(statementid)) {
            synchronized (obj) {
                if (!st.getConfiguration().hasStatement(statementid)) {
                    TextSqlNode textSqlNode = new TextSqlNode(sql);
                    SqlSource sqlSource = null;
                    if (textSqlNode.isDynamic()) {
                        sqlSource = new DynamicSqlSource(st.getConfiguration(), textSqlNode);
                    } else {
                        sqlSource = new RawSqlSource(st.getConfiguration(), sql, Map.class);
                    }
                    ResultMap.Builder resultBuilder = new ResultMap.Builder(st.getConfiguration(), statementid + "-Inline", Map.class, new ArrayList<ResultMapping>(), null);
                    List<ResultMap> resultMaps = new ArrayList<ResultMap>();
                    resultMaps.add(resultBuilder.build());
                    MappedStatement.Builder mappedBuilder = new MappedStatement.Builder(st.getConfiguration(), statementid, sqlSource, SqlCommandType.SELECT).resultMaps(resultMaps);

                    st.getConfiguration().addMappedStatement(mappedBuilder.build());
                }
            }
        }
		
		//比较SQL一致性，便于调试
		diffSQL(statementid,sql);
		
		List<Map<String,Object>> listObject = st.selectList(statementid, mapParams);
			
		int totalPage = pageHelper.getPages();
		long totalRow = pageHelper.getTotal();
		
		listData = ResultSetConvertUtil.getMap2BeanList(listObject, beanClass);
		
		page.setPageNum(pageNum);
		page.setPageSize(pageSize);
		page.setTotalPages(totalPage);
		page.setTotalRows(totalRow);
		page.setData(listData);	
			
		return page;		
	}

	public <T> Page<T> selectByPageOrderby(String statementid, String sql,Map<String,Object> mapParameter, String orderby ,long pageNum,long pageSize,Class<T> beanClass){
		
		List<T> listData =  new ArrayList<T>();
		Page<T> page = new Page<T>();
		
		int iPageNum = (int)pageNum;
		int iPageSize = (int)pageSize;
		com.github.pagehelper.Page<Object> pageHelper = PageHelper.startPage(iPageNum,iPageSize,orderby);
		
		SqlSessionTemplate st = (SqlSessionTemplate) getSqlSession();

        if (!st.getConfiguration().hasStatement(statementid)) {
            synchronized (obj) {
                if (!st.getConfiguration().hasStatement(statementid)) {
                    TextSqlNode textSqlNode = new TextSqlNode(sql);
                    SqlSource sqlSource = null;
                    if (textSqlNode.isDynamic()) {
                        sqlSource = new DynamicSqlSource(st.getConfiguration(), textSqlNode);
                    } else {
                        sqlSource = new RawSqlSource(st.getConfiguration(), sql, Map.class);
                    }

                    ResultMap.Builder resultBuilder = new ResultMap.Builder(st.getConfiguration(), statementid + "-Inline", Map.class, new ArrayList<ResultMapping>(), null);
                    List<ResultMap> resultMaps = new ArrayList<ResultMap>();
                    resultMaps.add(resultBuilder.build());
                    MappedStatement.Builder mappedBuilder = new MappedStatement.Builder(st.getConfiguration(), statementid, sqlSource, SqlCommandType.SELECT).resultMaps(resultMaps);

                    st.getConfiguration().addMappedStatement(mappedBuilder.build());
                }
            }
        }
		
		//比较SQL一致性，便于调试
		diffSQL(statementid,sql);
		
		List<Map<String,Object>> listObject = st.selectList(statementid, mapParameter);
			
		int totalPage = pageHelper.getPages();
		long totalRow = pageHelper.getTotal();
		
		listData = ResultSetConvertUtil.getMap2BeanList(listObject, beanClass);
		
		page.setPageNum(pageNum);
		page.setPageSize(pageSize);
		page.setTotalPages(totalPage);
		page.setTotalRows(totalRow);
		page.setData(listData);	
			
		return page;			
	}

	public Page<Map<String, Object>> selectMapByPageOrderby(String statementid, String sql,Map<String,Object> mapParameter, String orderby ,long pageNum,long pageSize){
		
		Page<Map<String, Object>> page = new Page<Map<String, Object>>();
		
		int iPageNum = (int)pageNum;
		int iPageSize = (int)pageSize;
		com.github.pagehelper.Page<Object> pageHelper = PageHelper.startPage(iPageNum,iPageSize,orderby);
		
		SqlSessionTemplate st = (SqlSessionTemplate) getSqlSession();

        if (!st.getConfiguration().hasStatement(statementid)) {
            synchronized (obj) {
                if (!st.getConfiguration().hasStatement(statementid)) {
                    TextSqlNode textSqlNode = new TextSqlNode(sql);
                    SqlSource sqlSource = null;
                    if (textSqlNode.isDynamic()) {
                        sqlSource = new DynamicSqlSource(st.getConfiguration(), textSqlNode);
                    } else {
                        sqlSource = new RawSqlSource(st.getConfiguration(), sql, Map.class);
                    }

                    ResultMap.Builder resultBuilder = new ResultMap.Builder(st.getConfiguration(), statementid + "-Inline", Map.class, new ArrayList<ResultMapping>(), null);
                    List<ResultMap> resultMaps = new ArrayList<ResultMap>();
                    resultMaps.add(resultBuilder.build());
                    MappedStatement.Builder mappedBuilder = new MappedStatement.Builder(st.getConfiguration(), statementid, sqlSource, SqlCommandType.SELECT).resultMaps(resultMaps);

                    st.getConfiguration().addMappedStatement(mappedBuilder.build());
                }
            }
        }
		
		//比较SQL一致性，便于调试
		diffSQL(statementid,sql);
		
		List<Map<String,Object>> listObject = st.selectList(statementid, mapParameter);
			
		int totalPage = pageHelper.getPages();
		long totalRow = pageHelper.getTotal();
		
		page.setPageNum(pageNum);
		page.setPageSize(pageSize);
		page.setTotalPages(totalPage);
		page.setTotalRows(totalRow);
		page.setData(listObject);	
			
		return page;			
	}
	
	public List<Map<String,Object>> executeQueryParam(String statementid, String sql, Map<String,Object> mapParams){
		
		SqlSessionTemplate st = (SqlSessionTemplate) getSqlSession();

        if (!st.getConfiguration().hasStatement(statementid)) {
            synchronized (obj) {
                if (!st.getConfiguration().hasStatement(statementid)) {
                    TextSqlNode textSqlNode = new TextSqlNode(sql);
                    SqlSource sqlSource = null;
                    if (textSqlNode.isDynamic()) {
                        sqlSource = new DynamicSqlSource(st.getConfiguration(), textSqlNode);
                    } else {
                        sqlSource = new RawSqlSource(st.getConfiguration(), sql, Map.class);
                    }

                    ResultMap.Builder resultBuilder = new ResultMap.Builder(st.getConfiguration(), statementid + "-Inline", Map.class, new ArrayList<ResultMapping>(), true);
                    List<ResultMap> resultMaps = new ArrayList<ResultMap>();
                    resultMaps.add(resultBuilder.build());
                    MappedStatement.Builder mappedBuilder = new MappedStatement.Builder(st.getConfiguration(), statementid, sqlSource, SqlCommandType.SELECT).resultMaps(resultMaps);

                    st.getConfiguration().addMappedStatement(mappedBuilder.build());
                }
            }
        }
		
		//比较SQL一致性，便于调试
		diffSQL(statementid,sql);
		
		List<Map<String,Object>> listObject = st.selectList(statementid, mapParams);	
		
		return listObject;
	}
//	
//	@Override
//	public <T> List<T> executeQueryBean(String sql,Class<T> beanClass){
//		
//		List<T> listData =  new ArrayList<T>();
//		SqlSession sqlSession = null;
//		Connection connection = null;
//		Statement statement = null;
//		ResultSet resultSet = null;
//		try {
//			SqlSessionTemplate st = (SqlSessionTemplate) getSqlSession();
//			
//			sqlSession = st.getSqlSessionFactory().openSession();
//			connection = sqlSession.getConnection();
//			
//			statement = connection.createStatement();
//
//			resultSet = statement.executeQuery(sql);
//			listData = ResultSetConvertUtil.getBeanList(resultSet,beanClass);
//			
//		} catch(Exception exp) {
//			throw exp;
//		} finally {
//			if(resultSet!=null) {
//				resultSet.close();
//			}			
//			if(statement!=null) {
//				statement.close();
//			}	
//			if(connection!=null) {
//				connection.close();
//			}
//			if(sqlSession!=null) {
//				sqlSession.close();
//			}
//		}		
//		return listData;
//	}
	
	public <T> List<T> executeQueryBeanByParam(String statementid, String sql, Map<String,Object> mapParams, Class<T> beanClass){
		
		List<T> listData =  new ArrayList<T>();

		SqlSessionTemplate st = (SqlSessionTemplate) getSqlSession();

        if (!st.getConfiguration().hasStatement(statementid)) {
            synchronized (obj) {
                if (!st.getConfiguration().hasStatement(statementid)) {
                    TextSqlNode textSqlNode = new TextSqlNode(sql);
                    SqlSource sqlSource = null;
                    if (textSqlNode.isDynamic()) {
                        sqlSource = new DynamicSqlSource(st.getConfiguration(), textSqlNode);
                    } else {
                        sqlSource = new RawSqlSource(st.getConfiguration(), sql, Map.class);
                    }
                    ResultMap.Builder resultBuilder = new ResultMap.Builder(st.getConfiguration(), statementid + "-Inline", Map.class, new ArrayList<ResultMapping>(), null);
                    List<ResultMap> resultMaps = new ArrayList<ResultMap>();
                    resultMaps.add(resultBuilder.build());
                    MappedStatement.Builder mappedBuilder = new MappedStatement.Builder(st.getConfiguration(), statementid, sqlSource, SqlCommandType.SELECT).resultMaps(resultMaps);

                    st.getConfiguration().addMappedStatement(mappedBuilder.build());
                }
            }
        }
		
		//比较SQL一致性，便于调试
		diffSQL(statementid,sql);
		
		List<Map<String,Object>> listObject = st.selectList(statementid, mapParams);			
			
		listData = ResultSetConvertUtil.getMap2BeanList(listObject,beanClass);
	
		return listData;
	}

	public int executeUpdateByParam(String statementid, String sql, Map<String,Object> mapParams){

		int result = 0;

		SqlSessionTemplate st = (SqlSessionTemplate) getSqlSession();

        if (!st.getConfiguration().hasStatement(statementid)) {
            synchronized (obj) {
                if (!st.getConfiguration().hasStatement(statementid)) {
                    TextSqlNode textSqlNode = new TextSqlNode(sql);
                    SqlSource sqlSource = null;
                    if (textSqlNode.isDynamic()) {
                        sqlSource = new DynamicSqlSource(st.getConfiguration(), textSqlNode);
                    } else {
                        sqlSource = new RawSqlSource(st.getConfiguration(), sql, Map.class);
                    }
                    // ResultMap.Builder resultBuilder = new ResultMap.Builder(st.getConfiguration(),statementid + "-Inline",Map.class,new ArrayList<ResultMapping>(),null);
                    MappedStatement.Builder mappedBuilder = new MappedStatement.Builder(st.getConfiguration(), statementid, sqlSource, SqlCommandType.UPDATE);

                    st.getConfiguration().addMappedStatement(mappedBuilder.build());
                }
            }
        }
		
		//比较SQL一致性，便于调试
		diffSQL(statementid,sql);
		
		result = st.update(statementid, mapParams);
		
		return result;
	}
	
	public int executeInsertByParam(String statementid, String sql, Map<String,Object> mapParams){

		int result = 0;

		SqlSessionTemplate st = (SqlSessionTemplate) getSqlSession();

		if(!st.getConfiguration().hasStatement(statementid)) {
		    synchronized(obj) {
		        if(!st.getConfiguration().hasStatement(statementid)) {
		            TextSqlNode textSqlNode = new TextSqlNode(sql);
		            SqlSource sqlSource = null;
		            if (textSqlNode.isDynamic()) {
		                sqlSource = new DynamicSqlSource(st.getConfiguration(), textSqlNode);
		            } else {
		                sqlSource = new RawSqlSource(st.getConfiguration(), sql, Map.class);
		            }
		            //ResultMap.Builder resultBuilder = new ResultMap.Builder(st.getConfiguration(),statementid + "-Inline",Map.class,new ArrayList<ResultMapping>(),null);
		            MappedStatement.Builder mappedBuilder = 
		                    new MappedStatement.Builder(st.getConfiguration(), statementid, sqlSource, SqlCommandType.INSERT);          
		            
		            st.getConfiguration().addMappedStatement(mappedBuilder.build());
		        }
		    }
		}
		
		//比较SQL一致性，便于调试
		diffSQL(statementid,sql);
		
		result = st.insert(statementid, mapParams);
		
		return result;
	}
	
	public int executeDeleteByParam(String statementid, String sql, Map<String,Object> mapParams){

		int result = 0;

		SqlSessionTemplate st = (SqlSessionTemplate) getSqlSession();

        if (!st.getConfiguration().hasStatement(statementid)) {
            synchronized (obj) {
                if (!st.getConfiguration().hasStatement(statementid)) {
                    TextSqlNode textSqlNode = new TextSqlNode(sql);
                    SqlSource sqlSource = null;
                    if (textSqlNode.isDynamic()) {
                        sqlSource = new DynamicSqlSource(st.getConfiguration(), textSqlNode);
                    } else {
                        sqlSource = new RawSqlSource(st.getConfiguration(), sql, Map.class);
                    }
                    // ResultMap.Builder resultBuilder = new ResultMap.Builder(st.getConfiguration(),statementid + "-Inline",Map.class,new ArrayList<ResultMapping>(),null);
                    MappedStatement.Builder mappedBuilder = new MappedStatement.Builder(st.getConfiguration(), statementid, sqlSource, SqlCommandType.DELETE);

                    st.getConfiguration().addMappedStatement(mappedBuilder.build());
                }
            }
        }
		
		//比较SQL一致性，便于调试
		diffSQL(statementid,sql);
		
		result = st.delete(statementid, mapParams);
		
		return result;
	}
	
	public List<Map<String,Object>> executeQuery(String statementid, String sql){
		
		SqlSessionTemplate st = (SqlSessionTemplate) getSqlSession();

        if (!st.getConfiguration().hasStatement(statementid)) {
            synchronized (obj) {
                if (!st.getConfiguration().hasStatement(statementid)) {
                    TextSqlNode textSqlNode = new TextSqlNode(sql);
                    SqlSource sqlSource = null;
                    if (textSqlNode.isDynamic()) {
                        sqlSource = new DynamicSqlSource(st.getConfiguration(), textSqlNode);
                    } else {
                        sqlSource = new RawSqlSource(st.getConfiguration(), sql, Map.class);
                    }

                    ResultMap.Builder resultBuilder = new ResultMap.Builder(st.getConfiguration(), statementid + "-Inline", Map.class, new ArrayList<ResultMapping>(), true);
                    List<ResultMap> resultMaps = new ArrayList<ResultMap>();
                    resultMaps.add(resultBuilder.build());
                    MappedStatement.Builder mappedBuilder = new MappedStatement.Builder(st.getConfiguration(), statementid, sqlSource, SqlCommandType.SELECT).resultMaps(resultMaps);

                    st.getConfiguration().addMappedStatement(mappedBuilder.build());
                }
            }
        }
		
		//比较SQL一致性，便于调试
		diffSQL(statementid,sql);
		
		List<Map<String,Object>> listObject = st.selectList(statementid);	
		
		return listObject;
	}
	
	private void diffSQL(String statementid, String sql) {

		if(mapStatementSQL.containsKey(statementid)) {
			String mappedSQL = mapStatementSQL.get(statementid);
			if(!mappedSQL.equals(sql)) {
				log.warn(">>>SQL is difference:"+statementid);
				log.warn(">>>old SQL:"+mappedSQL);
				log.warn(">>>new SQL:"+sql);
			}			
		} else {
			mapStatementSQL.put(statementid, sql);
		}
	}
	
}
